---@class Battlegrounds.Player : Base.Player
---@field public tavern_level integer @ 酒馆等级(1-6)
---@field public gold integer @ 金币数
---@field public board Minion[] @ 场上随从（最多7个）
---@field public hand Minion[] @ 手牌随从（最多10个）
---@field public shop Minion[] @ 商店随从（根据等级数量不同）
---@field public shop_spells Spell[] @ 商店法术
---@field public hp integer @ 生命值（初始40）
---@field public frozen boolean @ 是否冻结商店
---@field public armor integer @ 护甲值
---@field public rank integer @ 当前排名
---@field public eliminated boolean @ 是否被淘汰
local Player = Fk.Base.Player:subclass("Battlegrounds.Player")



--- 玩家分为客户端要处理的玩家，以及服务端处理的玩家两种。
---
--- 客户端能知道的玩家的信息十分有限，而服务端知道一名玩家的所有细节。
---
--- Player类就是这两种玩家的基类，包含它们共用的部分。
---
---@class Battlegrounds.Player
---@field public next Battlegrounds.Player
---@field public room Room
---@field public hp integer @ 体力值
---@field public maxHp integer @ 体力上限
---@field public shield integer @ 护甲数
---@field public general string @ 武将
---@field public deputyGeneral string @ 副将
---@field public gender integer @ 性别
---@field public seat integer @ 座位号
---@field public stage Stage @ 当前阶段
---@field public shop_maxcards integer @ 商店中的卡牌最大数量
---@field public shop_cards table<integer, integer[]> @ 商店中的卡牌
---@field public player_cards table<integer, integer[]> @ 当前拥有的所有牌，键是区域，值是id列表(手牌、战场)
---@field public dead boolean @ 是否死亡
---@field public cardUsedHistory table<string, integer[]> @ 用牌次数历史记录
---@field public skillUsedHistory table<string, integer[]> @ 发动技能次数的历史记录
---@field public player_skills Skill[] @ 当前拥有的所有技能
---@field public derivative_skills table<Skill, Skill[]> @ 角色派生技能，键为使获得此派生技能的源技能，值为派生技能表

function Player:initialize(_self)
  Fk.Base.Player.initialize(self)

  self.serverplayer = _self -- 控制者
  self._splayer = _self -- 真正在玩的玩家
  self._observers = { _self } -- "旁观"中的玩家，然而不包括真正的旁观者
  self.room = nil
  
  -- 初始化酒馆战旗特有字段
  self.tavern_level = 1
  self.gold = 3
  self.board = {}           -- 场上随从（最多7个）
  self.hand = {}            -- 手牌随从（最多10个）
  self.shop = {}            -- 商店随从
  self.shop_spells = {}     -- 商店法术
  self.hp = 40              -- 生命值（初始40）
  self.frozen = false       -- 是否冻结商店
  self.armor = 0            -- 护甲值
  self.rank = 0             -- 当前排名
  self.eliminated = false   -- 是否被淘汰
end

--- 购买随从
---@param index integer @ 商店中的索引
---@return boolean @ 是否购买成功
function Player:buyMinion(index)
  if index < 1 or index > #self.shop then
    return false
  end
  
  local minion = self.shop[index]
  if self.gold < minion.cost then
    return false
  end
  
  if #self.hand >= 10 then
    return false -- 手牌已满
  end
  
  -- 扣除金币
  self.gold = self.gold - minion.cost
  
  -- 从商店移除
  table.remove(self.shop, index)
  
  -- 添加到手牌
  table.insert(self.hand, minion)
  
  return true
end

--- 购买法术
---@param index integer @ 商店中的索引
---@return boolean @ 是否购买成功
function Player:buySpell(index)
  if index < 1 or index > #self.shop_spells then
    return false
  end
  
  local spell = self.shop_spells[index]
  if self.gold < spell.cost then
    return false
  end
  
  -- 扣除金币
  self.gold = self.gold - spell.cost
  
  -- 从商店移除
  table.remove(self.shop_spells, index)
  
  -- 立即使用法术
  return self:castSpell(spell)
end

--- 出售随从
---@param minion Minion @ 要出售的随从
---@return boolean @ 是否出售成功
function Player:sellMinion(minion)
  -- 从手牌中移除
  for i, m in ipairs(self.hand) do
    if m == minion then
      table.remove(self.hand, i)
      self.gold = self.gold + 1 -- 出售获得1金币
      return true
    end
  end
  
  -- 从场上移除
  for i, m in ipairs(self.board) do
    if m == minion then
      table.remove(self.board, i)
      self.gold = self.gold + 1 -- 出售获得1金币
      return true
    end
  end
  
  return false
end

--- 将随从放置到场上
---@param minion Minion @ 要放置的随从
---@param position integer? @ 位置（可选，默认放到末尾）
---@return boolean @ 是否放置成功
function Player:playMinion(minion, position)
  -- 检查手牌中是否有这个随从
  local found = false
  for i, m in ipairs(self.hand) do
    if m == minion then
      table.remove(self.hand, i)
      found = true
      break
    end
  end
  
  if not found then
    return false
  end
  
  -- 检查场上是否已满
  if #self.board >= 7 then
    -- 手牌已满，放回手牌
    table.insert(self.hand, minion)
    return false
  end
  
  -- 放置到场上
  if position and position >= 1 and position <= #self.board + 1 then
    table.insert(self.board, position, minion)
  else
    table.insert(self.board, minion)
  end
  
  return true
end

--- 刷新商店
---@return boolean @ 是否刷新成功
function Player:refreshShop()
  if self.gold < 1 then
    return false
  end
  
  self.gold = self.gold - 1
  
  -- 清空商店
  self.shop = {}
  self.shop_spells = {}
  
  -- 重新生成商店
  self:generateShop()
  
  return true
end

--- 升级酒馆
---@return boolean @ 是否升级成功
function Player:upgradeTavern()
  if self.tavern_level >= 6 then
    return false -- 已满级
  end
  
  local cost = self.tavern_level + 1 -- 升级费用 = 当前等级 + 1
  if self.gold < cost then
    return false
  end
  
  self.gold = self.gold - cost
  self.tavern_level = self.tavern_level + 1
  
  return true
end

--- 冻结/解冻商店
function Player:toggleFreeze()
  self.frozen = not self.frozen
end

--- 生成商店
function Player:generateShop()
  if self.frozen then
    return -- 商店被冻结，不重新生成
  end
  
  local engine = self.room.engine
  
  -- 生成随从（根据酒馆等级决定数量）
  local minion_count = math.min(self.tavern_level + 1, 7) -- 1级2个，2级3个...6级7个
  self.shop = engine:getRandomMinions(self.tavern_level, minion_count)
  
  -- 生成法术（如果有的话）
  local spell_count = math.min(math.floor(self.tavern_level / 2), 3) -- 每2级增加1个法术，最多3个
  if spell_count > 0 then
    self.shop_spells = engine:getRandomSpells(self.tavern_level, spell_count)
  end
end

--- 使用法术
---@param spell Spell @ 要使用的法术
---@param targets Player[]? @ 目标列表
---@return boolean @ 是否使用成功
function Player:castSpell(spell, targets)
  if not spell.effect then
    return false
  end
  
  return spell:cast(self, targets or {})
end

--- 受到伤害
---@param damage integer @ 伤害值
---@return integer @ 实际受到的伤害
function Player:takeDamage(damage)
  local actual_damage = damage
  
  -- 先扣除护甲
  if self.armor > 0 then
    local armor_reduction = math.min(actual_damage, self.armor)
    self.armor = self.armor - armor_reduction
    actual_damage = actual_damage - armor_reduction
  end
  
  -- 再扣除生命值
  if actual_damage > 0 then
    self.hp = self.hp - actual_damage
  end
  
  return damage -- 返回原始伤害值
end

--- 获得护甲
---@param amount integer @ 护甲值
function Player:gainArmor(amount)
  self.armor = self.armor + amount
end

--- 检查是否死亡
---@return boolean
function Player:isDead()
  return self.hp <= 0 or self.eliminated
end

--- 获取场上随从数量
---@return integer
function Player:getBoardSize()
  return #self.board
end

--- 获取手牌数量
---@return integer
function Player:getHandSize()
  return #self.hand
end

function Player:serialize()
  local o = Fk.Base.Player.serialize(self)

  -- 序列化酒馆战旗特有字段
  o.tavern_level = self.tavern_level
  o.gold = self.gold
  o.hp = self.hp
  o.frozen = self.frozen
  o.armor = self.armor
  o.rank = self.rank
  o.eliminated = self.eliminated
  
  -- 序列化随从（简化版，只保存名称）
  o.board = {}
  for _, minion in ipairs(self.board) do
    table.insert(o.board, minion.name)
  end
  
  o.hand = {}
  for _, minion in ipairs(self.hand) do
    table.insert(o.hand, minion.name)
  end
  
  o.shop = {}
  for _, minion in ipairs(self.shop) do
    table.insert(o.shop, minion.name)
  end

  return o
end

function Player:deserialize(o)
  Fk.Base.Player.deserialize(self, o)

  -- 反序列化酒馆战旗特有字段
  self.tavern_level = o.tavern_level or 1
  self.gold = o.gold or 3
  self.hp = o.hp or 40
  self.frozen = o.frozen or false
  self.armor = o.armor or 0
  self.rank = o.rank or 0
  self.eliminated = o.eliminated or false
  
  -- 反序列化随从（需要从引擎重新获取）
  self.board = {}
  self.hand = {}
  self.shop = {}
  
  -- TODO: 从引擎重新创建随从实例
end

return Player

